package com.mike.uaa.server.authentication.provider;

import cn.hutool.core.util.IdUtil;
import com.mike.uaa.core.Authentication;
import com.mike.uaa.core.DefaultAuthenticationToken;
import com.mike.uaa.core.User;
import com.mike.uaa.server.authentication.codec.BCryptCredentialEncryptor;
import com.mike.uaa.server.authentication.codec.CredentialEncryptor;
import com.mike.uaa.server.authentication.token.UsernamePasswordAuthenticationToken;
import com.mike.uaa.server.service.UserDetailService;
import com.mike.uaa.web.Exceptions;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.time.Instant;

/**
 * @author z zhang
 */
@Component
@RequiredArgsConstructor
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {

    private final CredentialEncryptor credentialEncryptor = new BCryptCredentialEncryptor();

    private final UserDetailService userDetailService;


    @Override
    public Authentication authenticate(Authentication authentication) {
        //强转
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;

        String username = (String) authenticationToken.getPrincipal();

        // 输入的密码
        String credential = (String) authenticationToken.getCredential();
        authenticationToken.eraseCredentials();
        // 从数据库查询出来的user对象
        User user = userDetailService.loadUserByUsername(username);

        if (user == null) {
            throw Exceptions.createUnauthorizedException("用户名密码错误");
        }
        //  验证密码
        if (!credentialEncryptor.matches(credential, user.getPassword())) {
            throw Exceptions.createInvalidPasswordException();
        }
        user.eraseCredentials();
        // 检查账号状态
        ValidAccountStatus(user);
        //构建成功的认证对象
        return DefaultAuthenticationToken.builder()
                .principal(user)
                .authenticated()
                .tokenValue(IdUtil.fastSimpleUUID())
                .issuedAt(Instant.now())
                .expiresIn(30 * 60)
                .build();
    }

    /**
     * 验证账号状态是否正常，如果账号状态异常则抛出{@link com.mike.uaa.web.ServiceException}
     *
     * @param user 等待验证的账号信息
     */
    private void ValidAccountStatus(User user) {
        // TODO 验证账号状态
    }

    @Override
    public boolean supports(Class<?> authenticationClass) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authenticationClass);
    }
}
